package org.cloudlab.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.cloudlab.bean.AcademicJournal;
import org.cloudlab.bean.Paper;
import org.cloudlab.bean.SubRecord;
import org.cloudlab.bean.SysUser;
import org.cloudlab.common.CommonConst;
import org.cloudlab.common.YesNoState;
import org.cloudlab.common.RecordState;
import org.cloudlab.common.RemoveState;
import org.cloudlab.mapper.SubRecordMapper;
import org.cloudlab.service.IAcademicJournalService;
import org.cloudlab.service.IPaperService;
import org.cloudlab.service.ISubRecordService;
import org.cloudlab.utils.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 投稿记录服务实现层
 *
 * @author Liu Yicong
 * @date 2023/9/8
 */
@Service
public class SubRecordServiceImpl extends ServiceImpl<SubRecordMapper, SubRecord> implements ISubRecordService {


	@Autowired
	private SubRecordMapper subRecordMapper;

	@Autowired
	@Lazy
	private IPaperService paperService;

	@Autowired
	@Lazy
	private IAcademicJournalService journalService;

	@Autowired
	private JwtTokenUtil tokenUtil;

	@Override
	@Transactional(rollbackFor = RuntimeException.class)
	public void add(SubRecord subRecord) {
		// 添加投稿记录到数据库
		SysUser currentUser = tokenUtil.getCurrentUser();

		Paper paper;
		AcademicJournal journal;

		// 查看期刊是否存在
		if (Objects.isNull(subRecord.getSubJournalId())) {
			AcademicJournal one = journalService.getOne(
					new LambdaQueryWrapper<AcademicJournal>()
							.eq(AcademicJournal::getJournalName, subRecord.getSubJournalName()));
			if (Objects.isNull(one)) {
				throw new RuntimeException("期刊为空, 请核对后在操作");
			} else {
				subRecord.setSubJournalId(one.getId());
			}
		}
		journal = journalService.getById(subRecord.getSubJournalId());
		if (Objects.isNull(journal)) {
			throw new RuntimeException("期刊不存在");
		}

		//查看文章是否存在
		if (Objects.isNull(subRecord.getPaperId())) {
			throw new RuntimeException("文章为空, 请核对后在操作");
		}
		paper = paperService.getById(subRecord.getPaperId());
		if (Objects.isNull(paper)) {
			throw new RuntimeException("文章不存在");
		}
		//查看当前用户是不是文章的责任人或者管理员
		if (!Objects.equals(paper.getBelongUserId(), currentUser.getId()) && !Objects.equals(currentUser.getId(), CommonConst.ADMIN_ID)) {
			throw new RuntimeException("你不是这篇文章的责任人");
		}

		//查看该文章已有的投稿记录, 如果之前的投稿记录状态仍然没有完成, 并且当前的投稿记录不是完结状态, 则不能新增
		String currentState = subRecord.getCurrentState();
		Long count = this.lambdaQuery().eq(SubRecord::getIsRemove, RemoveState.NOT_REMOVE.getValue()) // 未删除的记录
				.eq(SubRecord::getPaperId, subRecord.getPaperId()) // 等于文章id的记录
				.and(wrapperA -> wrapperA.ne(SubRecord::getCurrentState, RecordState.ACCEPTED.getValue())) //非接收的记录
				.and(wrapperR -> wrapperR.ne(SubRecord::getCurrentState, RecordState.REJECTED.getValue())) //非拒稿的记录
//				.and(wrapperD -> wrapperD.lt(SubRecord::getFinishTime, subRecord.getFinishTime())) //确定是否是最新的记录
				.count();
		if (count != 0
				&& !Objects.equals(currentState, RecordState.ACCEPTED.getValue())
				&& !Objects.equals(currentState, RecordState.REJECTED.getValue())) {
			throw new RuntimeException("这篇文章之前还有投稿记录没有完成哦, 先把之前的完成吧");
		}

		/*
		  2023/10/10 根据群众反应, 老师有可能要求多个文章同一时间投同一个期刊, 所以删除这个逻辑
		 */
		//查看期刊是否已经有文章在投
//		String isInSub = journal.getIsInSub();
//		if (Objects.nonNull(isInSub) && isInSub.equals(YesNoState.YES.getValue())) {
//			throw new RuntimeException("期刊已有其它文章在投了, 先看看其它的期刊吧");
//		}

		// 添加投稿记录
		subRecord.setCreateUserId(currentUser.getId());
		subRecord.setBelongNickName(currentUser.getNickName());
		subRecord.setBelongUserId(currentUser.getId());
		subRecord.setCreateTime(new Date());
		subRecord.setSubJournalName(journal.getJournalName());
		subRecord.setPaperAcronym(paper.getAcronym());
		subRecordMapper.insert(subRecord);

		// 更新文章记录
		boolean isFinished = false;
		if (Objects.nonNull(currentState)) {
			//这条记录是否已经完结
			isFinished = currentState.equals(RecordState.ACCEPTED.getValue()) ||
					currentState.equals(RecordState.REJECTED.getValue());
			//如果未完结则更新文章
			if (!isFinished) {
				paper.setSubJournalId(subRecord.getSubJournalId());
				paper.setSubJournalName(journal.getJournalName());
			}
		}
		paper.setCurrentState(subRecord.getCurrentState());
		paper.setStateDetails(subRecord.getStateDetails());
		paper.setSubTime(subRecord.getSubTime());
		paper.setTrackLink(subRecord.getTrackLink());
		paper.setUpdateTime(new Date());
		paper.setUpdateUserId(currentUser.getId());
		paperService.updateById(paper);

		//更新期刊信息
		//如果新增的投稿记录是已经被拒绝或者接收, 则不修改期刊的投稿状态
		//这条记录是否已经完结
		if (isFinished) {
			return;
		}
		// 可以在期刊中添加多个在投文章
		String originIds = journal.getInPaperId();
		String newIds = paper.getId().toString();
		if (Objects.nonNull(originIds) && !originIds.isEmpty()) {
			newIds = originIds + "," + paper.getId();
		}
		journal.setInPaperId(newIds);

		String originAcros = journal.getPaperAcronym();
		String newAcros = paper.getAcronym();
		if (Objects.nonNull(originAcros) && !originAcros.isEmpty()) {
			newAcros = originAcros + "," + newAcros;
		}
		journal.setPaperAcronym(newAcros);

		journal.setIsInSub(YesNoState.YES.getValue());
		journalService.updateById(journal);
	}

	@Override
	@Transactional(rollbackFor = RuntimeException.class)
	public void update(SubRecord subRecord) {
		// 添加投稿记录到数据库
		SysUser currentUser = tokenUtil.getCurrentUser();
		Long userId = currentUser.getId();
		Paper paper;
		AcademicJournal journal;

		//如果当前用户非所属用户且不是管理员则直接返回并报错
		if (!userId.equals(subRecord.getBelongUserId()) && !userId.equals(CommonConst.ADMIN_ID)) {
			throw new RuntimeException("无修改权限");
		}

		// 查看期刊是否存在
		if (Objects.isNull(subRecord.getSubJournalId())) {
			throw new RuntimeException("期刊为空, 请核对后在操作");
		}
		journal = journalService.getById(subRecord.getSubJournalId());
		if (Objects.isNull(journal)) {
			throw new RuntimeException("期刊不存在");
		}

		//查看文章是否存在
		if (Objects.isNull(subRecord.getPaperId())) {
			throw new RuntimeException("文章为空, 请核对后在操作");
		}
		paper = paperService.getById(subRecord.getPaperId());
		if (Objects.isNull(paper)) {
			throw new RuntimeException("文章不存在");
		}

		//如果记录之前就已经完结了则不再更新这个记录的状态
//		String elderState = this.getById(subRecord.getId()).getCurrentState();
//		if (Objects.nonNull(elderState)) {
//			if (elderState.equals(RecordState.ACCEPTED.getValue()) || elderState.equals((RecordState.REJECTED.getValue()))) {
//				throw new RuntimeException("不能修改已经完结的记录了喔");
//			}
//		}

//		//查看期刊是否已经有文章在投
//		String isInSub = journal.getIsInSub();
//		if (Objects.nonNull(isInSub) && isInSub.equals(CommonConst.YES)) {
//			throw new RuntimeException("该期刊已有文章在投, 请核对后再进行操作");
//		}

		//更新投稿记录
		subRecord.setUpdateUserId(userId);
		subRecord.setUpdateTime(new Date());
		subRecordMapper.updateById(subRecord);

		// 更新文章记录
		paper.setCurrentState(subRecord.getCurrentState());
		paper.setStateDetails(subRecord.getStateDetails());
		paper.setSubTime(subRecord.getSubTime());
		paper.setSubJournalId(subRecord.getSubJournalId());
		paper.setSubJournalName(journal.getJournalName());
		paper.setTrackLink(subRecord.getTrackLink());
		paper.setUpdateTime(new Date());
		paper.setUpdateUserId(userId);
		paperService.updateById(paper);

		//更新期刊记录
		//根据期刊当前的状态和投稿记录来修改期刊的状态
		String currentState = subRecord.getCurrentState();
		boolean isFinished = false;
		if (Objects.nonNull(currentState)) {
			//这条记录是否已经完结
			isFinished = currentState.equals(RecordState.ACCEPTED.getValue()) ||
					currentState.equals(RecordState.REJECTED.getValue());
		}

		/*
		2023/10/10 根据群众反应, 老师有可能要求多个文章同一时间投同一个期刊, 所以删除这个逻辑
		 */
		// 判断是否释放期刊
		// 如果期刊绑定的投稿文章和当前记录一致, 则判断是否完结
		//完结: 释放期刊, InSub状态修改为NO;
		//未完结: 不释放期刊, InSub状态不变, 仍未YES
//		if (Objects.equals(journal.getInPaperId(), paper.getId())) {
//			if (isFinished) {
//				journal.setInPaperId(null);
//				journal.setPaperAcronym(null);
//				journal.setIsInSub(YesNoState.NO.getValue());
//				journalService.updateById(journal);
//			}
//		}

		// TODO 判断是否修改期刊的在投状态/在投文章名/在投文章ID
		String originIds = journal.getInPaperId();
		// 如果期刊绑定的投稿文章中包含当前记录, 则判断是否这次更新是否是完结状态
		if (Objects.nonNull(originIds) && originIds.contains(paper.getId().toString())) {
			// 完结: 修改期刊在投状态/在投文章名/在投文章ID;
			// 未完结: 不修改期刊
			if (isFinished) {
				String newIds = separatorFilter(originIds, paper.getId().toString());
				journal.setInPaperId(newIds);
				journal.setPaperAcronym(separatorFilter(journal.getPaperAcronym(), paper.getAcronym()));
				if (Objects.isNull(newIds) || newIds.isEmpty()) {
					journal.setIsInSub(YesNoState.NO.getValue());
				}
				journalService.updateById(journal);
			}
		}
	}

	/**
	 * 使用分隔符的过滤器
	 * 例如: 如果需要删除字符串中的b
	 * "a,b,c" -> "a,c"
	 * "a,b" -> "a"
	 * "b" -> ""
	 *
	 * @param origin 原字符串
	 * @param remove 需要删除的字符串
	 * @return 新字符串
	 */
	public String separatorFilter(String origin, String remove) {
		return Arrays.stream(origin.split(CommonConst.SEPARATOR)) //将原字符串分隔为数组
				.filter(e -> !e.equals(remove)) // 过滤掉需要删除的元素
				.map(String::valueOf)// 将每个元素转换为String
				.collect(Collectors.joining(","));// 使用 joining 拼接;
	}

	@Override
	public void deleteBySubRecordId(Long subRecordId) {
		SysUser currentUser = tokenUtil.getCurrentUser();
		Long userId = currentUser.getId();
		Paper paper;
		AcademicJournal journal;
		SubRecord subRecord = subRecordMapper.selectById(subRecordId);

		if (Objects.isNull(subRecord)) {
			throw new RuntimeException("投稿记录不存在");
		}

		if (!userId.equals(subRecord.getBelongUserId())) {
			throw new RuntimeException("无删除权限");
		}

		// 查看期刊是否存在
		if (Objects.isNull(subRecord.getSubJournalId())) {
			throw new RuntimeException("期刊为空, 请核对后在操作");
		}
		journal = journalService.getById(subRecord.getSubJournalId());
		if (Objects.isNull(journal)) {
			throw new RuntimeException("期刊不存在");
		}

		//查看文章是否存在
		if (Objects.isNull(subRecord.getPaperId())) {
			throw new RuntimeException("文章为空, 请核对后在操作");
		}
		paper = paperService.getById(subRecord.getPaperId());
		if (Objects.isNull(paper)) {
			throw new RuntimeException("文章不存在");
		}


		/*
		2023/10/10 根据群众反应, 老师有可能要求多个文章同一时间投同一个期刊, 所以删除这个逻辑
		 */
//		journal.setInPaperId(null);
//		journal.setPaperAcronym(null);
//		journal.setIsInSub(YesNoState.NO.getValue());

		// 更新期刊信息
		String originIds = journal.getInPaperId();
		// 如果期刊绑定的投稿文章中包含当前记录, 则删除期刊中的在投信息
		if (Objects.nonNull(originIds) && originIds.contains(paper.getId().toString())) {
			String newIds = separatorFilter(originIds, paper.getId().toString());
			journal.setInPaperId(newIds);
			journal.setPaperAcronym(separatorFilter(journal.getPaperAcronym(), paper.getAcronym()));
			if (Objects.isNull(newIds) || newIds.isEmpty()) {
				journal.setIsInSub(YesNoState.NO.getValue());
			}
		}
		journalService.updateById(journal);

		// 更新文章记录
		paper.setCurrentState(null);
		paper.setStateDetails(null);
		paper.setSubTime(null);
		paper.setSubJournalId(null);
		paper.setSubJournalName(null);
		paper.setUpdateTime(new Date());
		paper.setUpdateUserId(userId);
		paperService.updateById(paper);

		subRecord.setIsRemove(RemoveState.REMOVED.getValue());
		subRecord.setUpdateTime(new Date());
		subRecord.setUpdateUserId(currentUser.getId());
		subRecordMapper.updateById(subRecord);
	}

	@Override
	public Page<SubRecord> queryByPage(Page<SubRecord> page, String onlyOwn, String paperName) {
		Long userId = null;
		if (StringUtils.isNotEmpty(onlyOwn) && onlyOwn.equals(YesNoState.YES.getValue())) {
			SysUser currentUser = tokenUtil.getCurrentUser();
			userId = currentUser.getId();
		}
		return subRecordMapper.queryByPage(page, userId, paperName);
	}

	@Override
	public Page<SubRecord> queryByPaperId(Page<SubRecord> page, Long paperId) {
		return subRecordMapper.queryByPaperId(page, paperId);
	}

	@Override
	public Page<SubRecord> queryByJournalId(Page<SubRecord> page, Long journalId) {
		return subRecordMapper.queryByJournalId(page, journalId);
	}

	@Override
	public void deleteBatchByJournalId(Long journalId) {
		List<SubRecord> list = this.lambdaQuery().eq(SubRecord::getIsRemove, RemoveState.NOT_REMOVE.getValue())
				.eq(SubRecord::getSubJournalId, journalId).list();
		if (Objects.nonNull(list) && !list.isEmpty()) {
			for (SubRecord subRecord : list) {
				subRecord.setIsRemove(RemoveState.REMOVED.getValue());
				subRecordMapper.updateById(subRecord);
			}
		}
	}

	@Override
	public void deleteByPaperId(Long paperId) {
		List<SubRecord> list = this.lambdaQuery().eq(SubRecord::getIsRemove, RemoveState.NOT_REMOVE.getValue())
				.eq(SubRecord::getPaperId, paperId).list();
		if (Objects.nonNull(list) && !list.isEmpty()) {
			for (SubRecord subRecord : list) {
				subRecord.setIsRemove(RemoveState.REMOVED.getValue());
				subRecordMapper.updateById(subRecord);
			}
		}
	}

}
